


// 通过路径获取文件名 + 扩展名
XXAPI wstr Path_FileNameExtW(wstr sPath)
{
	if ( sPath == NULL ) { return (wstr)xCore.nullstring; }
	wstr sRet = wcsrchr(sPath, L'\\');
	if ( sRet ) {
		return xCore_CopyStringW(&sRet[1], 0);
	} else {
		return xCore_CopyStringW(sPath, 0);
	}
}
XXAPI astr Path_FileNameExtA(astr sPath)
{
	if ( sPath == NULL ) { return (astr)xCore.nullstring; }
	astr sRet = strrchr(sPath, '\\');
	if ( sRet ) {
		return xCore_CopyStringA(&sRet[1], 0);
	} else {
		return xCore_CopyStringA(sPath, 0);
	}
}



// 通过路径获取文件名
XXAPI wstr Path_FileNameW(wstr sPath)
{
	if ( sPath == NULL ) { return (wstr)xCore.nullstring; }
	wstr sFile = Path_FileNameExtW(sPath);
	wstr sRet = wcsrchr(sFile, L'.');
	if ( sRet ) {
		sRet[0] = 0;
	}
	return sFile;
}
XXAPI astr Path_FileNameA(astr sPath)
{
	if ( sPath == NULL ) { return (astr)xCore.nullstring; }
	astr sFile = Path_FileNameExtA(sPath);
	astr sRet = strrchr(sFile, '.');
	if ( sRet ) {
		sRet[0] = 0;
	}
	return sFile;
}



// 通过路径获取扩展名
XXAPI wstr Path_FileExtW(wstr sPath)
{
	if ( sPath == NULL ) { return (wstr)xCore.nullstring; }
	wstr sFile = Path_FileNameExtW(sPath);
	wstr sRet = wcsrchr(sPath, L'.');
	if ( sRet ) {
		sRet = xCore_LCaseW(&sRet[1], 0, FALSE);
		xCore_free(sFile);
		return sRet;
	} else {
		xCore_free(sFile);
		return (wstr)xCore.nullstring;
	}
}
XXAPI astr Path_FileExtA(astr sPath)
{
	if ( sPath == NULL ) { return (astr)xCore.nullstring; }
	astr sFile = Path_FileNameExtA(sPath);
	astr sRet = strrchr(sPath, '.');
	if ( sRet ) {
		sRet = xCore_LCaseA(&sRet[1], 0, FALSE);
		xCore_free(sFile);
		return sRet;
	} else {
		xCore_free(sFile);
		return xCore.nullstring;
	}
}



// 通过路径获取文件夹(以 \ 结尾)
XXAPI wstr Path_FilePathW(wstr sPath)
{
	if ( sPath == NULL ) { return (wstr)xCore.nullstring; }
	wstr sRet = wcsrchr(sPath, L'\\');
	if ( sRet ) {
		return xCore_CopyStringW(sPath, (sRet - sPath) + 1);
	} else {
		return (wstr)xCore.nullstring;
	}
}
XXAPI astr Path_FilePathA(astr sPath)
{
	if ( sPath == NULL ) { return (astr)xCore.nullstring; }
	astr sRet = strrchr(sPath, '\\');
	if ( sRet ) {
		return xCore_CopyStringA(sPath, (sRet - sPath) + 1);
	} else {
		return xCore.nullstring;
	}
}



// 判断是否为绝对路径（Linux 系统以 / 开头为绝对路径，Windows系统含 : 为绝对路径）
XXAPI int Path_IsAbsA(astr sPath)
{
	if ( sPath[0] == '/' ) {
		return TRUE;
	}
	int iCount = strlen(sPath);
	for ( int i = 0; i < iCount; i++ ) {
		if ( sPath[i] == ':' ) {
			return TRUE;
		}
	}
	return FALSE;
}
XXAPI int Path_IsAbsW(wstr sPath)
{
	if ( sPath[0] == L'/' ) {
		return TRUE;
	}
	int iCount = wcslen(sPath);
	for ( int i = 0; i < iCount; i++ ) {
		if ( sPath[i] == L':' ) {
			return TRUE;
		}
	}
	return FALSE;
}



// 判断是否为相对路径
XXAPI int Path_IsRelA(astr sPath)
{
	if ( Path_IsAbsA(sPath) ) {
		return FALSE;
	} else {
		return TRUE;
	}
}
XXAPI int Path_IsRelW(wstr sPath)
{
	if ( Path_IsAbsW(sPath) ) {
		return FALSE;
	} else {
		return TRUE;
	}
}



// 获取绝对路径
XXAPI wstr Path_GetAbsW(wstr sPath, wstr sCurPath)
{
	if ( sPath == NULL ) { return (wstr)xCore.nullstring; }
	if ( PathIsRelativeW(sPath) ) {
		wstr sRet = malloc(MAX_PATH * sizeof(wchar_t));
		int bFree = 0;
		if ( sCurPath == NULL ) {
			sCurPath = _wgetcwd(NULL, 0);
			bFree = -1;
		}
		PathCombineW(sRet, sCurPath, sPath);
		if ( bFree ) { free(sCurPath); }
		return sRet;
	} else {
		return xCore_CopyStringW(sPath, 0);
	}
}
XXAPI astr Path_GetAbsA(astr sPath, astr sCurPath)
{
	if ( PathIsRelativeA(sPath) ) {
		astr sRet = malloc(MAX_PATH);
		int bFree = 0;
		if ( sCurPath == NULL ) {
			sCurPath = getcwd(NULL, 0);
			bFree = -1;
		}
		PathCombineA(sRet, sCurPath, sPath);
		if ( bFree ) { free(sCurPath); }
		return sRet;
	} else {
		return xCore_CopyStringA(sPath, 0);
	}
}



// 获取相对路径
XXAPI wstr Path_GetRelW(wstr sPath, wstr sCurPath)
{
	wstr sRet = malloc(MAX_PATH * sizeof(wchar_t));
	int bFree = 0;
	if ( sCurPath == NULL ) {
		sCurPath = _wgetcwd(NULL, 0);
		bFree = -1;
	}
	int iPath = PathIsDirectoryW(sPath)    ? FILE_ATTRIBUTE_DIRECTORY : 0;
	int iCur  = PathIsDirectoryW(sCurPath) ? FILE_ATTRIBUTE_DIRECTORY : 0;
	PathRelativePathToW(sRet, sCurPath, iCur, sPath, iPath);
	if ( bFree ) { free(sCurPath); }
	return sRet;
}
XXAPI astr Path_GetRelA(astr sPath, astr sCurPath)
{
	astr sRet = malloc(MAX_PATH);
	int bFree = 0;
	if ( sCurPath == NULL ) {
		sCurPath = getcwd(NULL, 0);
		bFree = -1;
	}
	int iPath = PathIsDirectoryA(sPath)    ? FILE_ATTRIBUTE_DIRECTORY : 0;
	int iCur  = PathIsDirectoryA(sCurPath) ? FILE_ATTRIBUTE_DIRECTORY : 0;
	PathRelativePathToA(sRet, sCurPath, iCur, sPath, iPath);
	if ( bFree ) { free(sCurPath); }
	return sRet;
}



// 获取随机不存在的路径
XXAPI wstr Path_RandomW(wstr sHead, wstr sFoot, int iRand)
{
	int iSizeHead = wcslen(sHead);
	int iSize = iSizeHead + wcslen(sFoot) + iRand + 1;
	wstr sRet = malloc(iSize * sizeof(wchar_t));
	wcscpy(sRet, sHead);
	for ( int i = 0; i < iRand; i++ ) {
		int iChar = xCore_Rand(0x30, 0x5A - 7);
		if ( iChar > 0x39 ) { iChar += 7; }
		sRet[iSizeHead + i] = iChar;
	}
	wcscpy(&sRet[iSizeHead + iRand], sFoot);
	sRet[iSize - 1] = 0;
	return sRet;
}
XXAPI astr Path_RandomA(astr sHead, astr sFoot, int iRand)
{
	int iSizeHead = strlen(sHead);
	int iSize = iSizeHead + strlen(sFoot) + iRand + 1;
	astr sRet = malloc(iSize);
	strcpy(sRet, sHead);
	for ( int i = 0; i < iRand; i++ ) {
		int iChar = xCore_Rand(0x30, 0x5A - 7);
		if ( iChar > 0x39 ) { iChar += 7; }
		sRet[iSizeHead + i] = iChar;
	}
	strcpy(&sRet[iSizeHead + iRand], sFoot);
	sRet[iSize - 1] = 0;
	return sRet;
}



// 文件路径合法性检查（返回 TRUE 代表路径有问题）
XXAPI int Path_SafeCheckW(wstr sPath, int bRepair)
{
	if ( sPath == NULL ) { return TRUE; }
	wstr sNewPath = xCore_ReplaceW(sPath, L"/", L"\\");
	wstr* arrText = xCore_SplitCharW(sNewPath, L'\\', TRUE);
	int iCount = xCore.iRetSize;
	int bRet = FALSE;
	if ( bRepair ) { sPath[0] = 0; }
	for ( int i = 0; i < iCount; i++ ) {
		xxTrimW(arrText[i], L" .", TRUE);					// 过滤文件开头和末尾的空格和 . 符号
		int bSize = xCore.iRetSize;
		xxStringFilterW(arrText[i], L"*\"<>|", TRUE);		// 去除不允许存在的字符（ : 和 ? 不过滤）
		if ( bSize || xCore.iRetSize ) { bRet = TRUE; }
		if ( bRepair ) {
			wcscat(sPath, arrText[i]);
			if ( i + 1 != iCount ) { wcscat(sPath, L"\\"); }
		}
	}
	xCore_free(arrText);
	return bRet;
}
XXAPI int Path_SafeCheckA(astr sPath, int bRepair)
{
	wstr sPathW = xCore_M2W(sPath, CP_ACP, 0);
	int bRet = Path_SafeCheckW(sPathW, bRepair);
	if ( bRepair ) {
		astr sNewPath = xCore_W2M(sPathW, CP_ACP, 0);
		strcpy(sPath, sNewPath);
		xCore_free(sNewPath);
	}
	xCore_free(sPathW);
	return bRet;
}



// 根据 文件夹 + 文件 合并完整的路径，自动补充文件夹末尾的斜杠（需要使用 xCore_free 释放内存）
XXAPI wstr Path_JoinW(wstr sPath, wstr sFile)
{
	if ( sFile == NULL ) { xCore.iRet = 0; return (wstr)xCore.nullstring; }
	wstr sRet;
	int iSize = wcslen(sPath);
	if ( (sPath == NULL) || (iSize == 0) ) {
		sPath = xCore_AppPathW();
		sRet = xCore_FormatW(L"%s%s", sPath, sFile);
		xCore_free(sPath);
	} else {
		if ( (sPath[iSize - 1] == L'/') || (sPath[iSize - 1] == L'\\') ) {
			sRet = xCore_FormatW(L"%s%s", sPath, sFile);
		} else {
			sRet = xCore_FormatW(L"%s\\%s", sPath, sFile);
		}
	}
	return sRet;
}
XXAPI astr Path_JoinA(astr sPath, astr sFile)
{
	if ( sFile == NULL ) { xCore.iRet = 0; return (astr)xCore.nullstring; }
	astr sRet;
	int iSize = (sPath == NULL) ? 0 : strlen(sPath);
	if ( iSize == 0 ) {
		sPath = xCore_AppPathA();
		sRet = xCore_FormatA("%s%s", sPath, sFile);
		xCore_free(sPath);
	} else {
		if ( (sPath[iSize - 1] == '/') || (sPath[iSize - 1] == '\\') ) {
			sRet = xCore_FormatA("%s%s", sPath, sFile);
		} else {
			sRet = xCore_FormatA("%s\\%s", sPath, sFile);
		}
	}
	return sRet;
}



// 判断两个路径是否可以形成相对路径（不区分大小写，自动适配 / 和 \ 符号）
XXAPI int Path_RelLikeW(wstr sPath, wstr sFile)
{
	size_t iSize = wcslen(sPath);
	int bRet = -1;
	for ( int i = 0; i < iSize; i++ ) {
		if ( (sPath[i] == '/') || (sPath[i] == '\\') ) {
			if ( (sFile[i] != '/') && (sFile[i] != '\\') ) {
				bRet = 0;
				break;
			}
		} else if ( tolower(sPath[i]) != tolower(sFile[i]) ) {
			bRet = 0;
			break;
		}
	}
	return bRet;
}
XXAPI int Path_RelLikeA(astr sPath, astr sFile)
{
	size_t iSize = strlen(sPath);
	int bRet = -1;
	for ( int i = 0; i < iSize; i++ ) {
		if ( (sPath[i] == '/') || (sPath[i] == '\\') ) {
			if ( (sFile[i] != '/') && (sFile[i] != '\\') ) {
				bRet = 0;
				break;
			}
		} else if ( tolower(sPath[i]) != tolower(sFile[i]) ) {
			bRet = 0;
			break;
		}
	}
	return bRet;
}


